package com.nenglai.common.captcha;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author kongdehui
 * @date 2021/04/24 14:13
 **/
public class CaptchaHelper {
    /**
     * 待验证的验证码
     */
    Map<String, Element> captchaContainer = new ConcurrentHashMap<>();

    /**
     * 过期时间
     */
    private Long countdown = 120000L;

    public CaptchaHelper(Long countdown) {
        this.countdown = countdown;
    }

    public CaptchaHelper() {}

    /**
     * 获取管理器
     * 
     * @author kongdehui
     * @date 2021/04/24 14:48
     * @return java.util.Map<java.lang.String,com.xiaositea.admin.kernel.captcha.CaptchaHelper.Element>
     */
    public Map<String, Element> getCaptchaContainer() {
        return captchaContainer;
    }

    public String key() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public void addElement(String key, String value) {
        captchaContainer.put(key, new Element(value, countdown, new Date()));
    }

    public void addElement(String key, String value, Long countdown) {
        captchaContainer.put(key, new Element(value, countdown, new Date()));
    }

    public boolean verifyOnce(String key, String target) throws CaptchaException {
        if (verify(key, target)) {
            captchaContainer.remove(key);
            return true;
        }
        return false;
    }

    public boolean verify(String key, String target) throws CaptchaException {
        if (!captchaContainer.containsKey(key)) {
            throw new CaptchaException("无效验证码");
        }

        Element element = captchaContainer.get(key);
        if (element.expired()) {
            throw new CaptchaException("验证码已过期");
        }
        return element.getValue().equals(target);
    }

    @AllArgsConstructor
    @Data
    public static class Element {
        private String value;
        private Long countdown;
        private Date start;

        public boolean expired() {
            long now = new Date().getTime();
            long start = this.start.getTime();
            return now - start > countdown;
        }
    }
}
